﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Objects;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using DoAnForum.Models;
using Ext.Net;
using Ext.Net.MVC;
using System.Linq.Dynamic;
using log4net;

namespace DoAnForum.Controllers
{
    [DirectController]
    public class AccountController : Controller
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(AccountController).Name);
        private static DoAnForumEntities db = new DoAnForumEntities();
        public IFormsAuthenticationService FormsService { get; set; }
        public IMembershipService MembershipService { get; set; }

        protected override void Initialize(RequestContext requestContext)
        {
            if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
            if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
            base.Initialize(requestContext);
        }


        // **************************************
        // URL: /Account/ForgotPassword
        // **************************************

        public ActionResult AcessDenied()
        {
            return View();
        }
        
        public ActionResult ForgotPassword()
        {
            return View();
        }

        [HttpPost]
        public ActionResult ForgotPassword(ForgotPassword model)
        {
            if (ModelState.IsValid)
            {
                MembershipUser user = Membership.GetUser(model.UserName);
                try
                {
                    if (user.Email != model.Email)
                    {
                        X.Msg.Alert("ERROR", "The Email provided is incorrect.").Show();
                    }
                    else
                    {
                        var temp = db.aspnet_Users.Single(m => m.UserName == model.UserName);
                        string resetPass = temp.UserId.ToString().Substring(0, 8);
                        user.ChangePassword(user.ResetPassword(), resetPass);
                        var user1 = db.aspnet_Membership.Single(m => m.UserId == temp.UserId);
                        user1.Comment = "need change pass";
                        db.SaveChanges();
                        string body = "Hello " + model.UserName + "!" + "\n Your new password is : " + resetPass;
                        try
                        {
                            ForgotPassService.SendMail(model.Email, body);
                            X.Msg.Alert("Sucess", "Your new password has been sent to your mail").Show();
                            return RedirectToAction("ForgotPasswordSuccess");
                        }
                        catch (Exception ex)
                        {
                            log.Error("Can't send email: " + ex.Message);
                            X.Msg.Alert("Can't send email", "UserName or Email provided is incorrect.").Show();
                        }
                    }
                }
                catch (Exception)
                {
                    X.Msg.Alert("ERROR", "UserName provided is incorrect.").Show();
                }
                
            }

            // If we got this far, something failed, redisplay form
            return this.FormPanel();
        }

        public ActionResult ForgotPasswordSuccess()
        {
            return View();
        }

        // **************************************
        // URL: /Account/LogOff
        // **************************************

        public ActionResult LogOff()
        {
            FormsService.SignOut();
            return RedirectToAction("Index", "Home");
        }

        // **************************************
        // URL: /Account/LogOn
        // **************************************

        public ActionResult LogOn()
        {
            return View();
        }

        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ValidateUser(model.UserName, model.Password))
                {
                    FormsService.SignIn(model.UserName, model.RememberMe);
                    var temp = db.aspnet_Users.Single(m => m.UserName == model.UserName);
                    var user = db.aspnet_Membership.Single(m => m.UserId == temp.UserId);
                    const string comment = "need change pass";
                    if (user.Comment != null)
                    {
                        string test = user.Comment.ToString(CultureInfo.InvariantCulture);
                        if(comment.Equals(test))
                        {
                            return RedirectToAction("ChangePassword");
                        }
                    }
                    else if (Url.IsLocalUrl(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    X.Msg.Alert("ERROR", "The user name or password provided is incorrect.").Show();
                }
            }

            // If we got this far, something failed, redisplay form
            return this.FormPanel();
        }

        // **************************************
        // URL: /Account/Register
        // **************************************

        //[AccessDeniedAuthorize(Roles = "Admin")]
        public ActionResult Register()
        {
            return View();
        }

        //[Authorize(Roles = "Admin")]
        [HttpPost]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);

                if (createStatus == MembershipCreateStatus.Success)
                {
                    //var cbb = X.GetCmp<ComboBox>("CBBRole");
                    Roles.AddUserToRoles(model.UserName, new[] {"Member"});
                    var user = new User();
                    var temp = db.aspnet_Users.SingleOrDefault(x => x.UserName == model.UserName);
                    if (temp != null)
                    {
                        user.UserId = temp.UserId;
                        user.UserSignature = model.UserSignature;
                        user.UserBirthDate = model.BirthDay;
                        var upImage = X.GetCmp<FileUploadField>("UpImage");
                        if (upImage.HasFile)
                        {
                            var httpPostedFileBase = Request.Files[0];
                            if (httpPostedFileBase != null)
                            {
                                httpPostedFileBase.SaveAs(Server.MapPath("~/") + "//Content//Logo//" +
                                                          httpPostedFileBase.FileName);
                                user.UserPhoto = "/Content/Logo/" + httpPostedFileBase.FileName;
                            }
                        }
                        else
                        {
                            user.UserPhoto = "/Content/Logo/defaultLogo45.jpg";
                        }
                        db.Users.AddObject(user);
                        db.SaveChanges();
                    }
                    // return to list user
                    return RedirectToAction("RegisterSuccess");
                }
                else
                {
                    string error = AccountValidation.ErrorCodeToString(createStatus);
                    X.Msg.Alert("ERROR", error).Show();
                    log.Error("ERROR: "+error);
                }
            }

            return View(model);
        }

        public ActionResult RegisterSuccess()
        {
            return View();
        }

        // **************************************
        // URL: /Account/ChangePassword
        // **************************************

        [Authorize]
        public ActionResult ChangePassword()
        {
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View();
        }

        [Authorize]
        public ActionResult ChangePasswordAdmin()
        {
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult ChangePasswordComit(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {
                
                if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
                {
                    return RedirectToAction("ChangePasswordStatus");
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                    X.Msg.Alert("Error!", "The Old password provided is incorrect").Show();
                }
            }

            // If we got this far, something failed, redisplay form
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return this.FormPanel();
        }

        public ActionResult ChangePasswordStatus()
        {
            var temp = db.aspnet_Users.Single(m => m.UserName == User.Identity.Name);
            var user1 = db.aspnet_Membership.Single(m => m.UserId == temp.UserId);
            user1.Comment = null;
            db.SaveChanges();
            return RedirectToAction("ChangePasswordSuccess");
        }

        // **************************************
        // URL: /Account/ChangePasswordSuccess
        // **************************************

        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

        // **************************************
        // URL: /Account/ListAcount
        // **************************************

        [AccessDeniedAuthorize(Roles = "Admin")]
        public ActionResult ListAcount()
        {
            Session["includeInActiveAccount"] = false;
            Session["CharFilterAccount"] = "";

            return View();
        }

        public ActionResult IncludeInActive()
        {
            var store = X.GetCmp<Store>("AccountStore");

            Session["includeInActiveAccount"] = !(bool)Session["includeInActiveAccount"];

            store.Reload();
            return this.Direct();
        }

        [DirectMethod]
        public ActionResult InActiveAccount(string a)
        {
            string test = "\"";
            var store = X.GetCmp<Store>("AccountStore");
            for (int i = 2; i < (a.Length-1); i++)
            {
                if (','.Equals(a[i])) i += 2;
                string temp = null;
                while (!(','.Equals(a[i])) && !(']'.Equals(a[i])) && !(test.Equals(a[i].ToString())))
                {
                    temp = temp + a[i];
                    i++;
                }
                aspnet_Users user = db.aspnet_Users.Single(c => c.UserName.Equals(temp));
                aspnet_Membership member = db.aspnet_Membership.Single(c => c.UserId == user.UserId);
                db.aspnet_Membership.Detach(member);
                member.IsApproved = !member.IsApproved;
                db.aspnet_Membership.Attach(member);
                db.ObjectStateManager.ChangeObjectState(member, EntityState.Modified);
                db.SaveChanges();
            }
            X.Msg.Alert("Sucess", "Edit Acount success!").Show();
            store.Reload();
            return this.FormPanel();
        }

        [DirectMethod]
        public ActionResult CharFilterAccount(string filterstring)
        {
            var store = X.GetCmp<Store>("AccountStore");
            Session["CharFilterAccount"] = filterstring;
            store.Reload();
            return this.Direct();
        }

        public ActionResult BindingStore(StoreRequestParameters parameters)
        {
            var sampleData = (from tab1 in db.aspnet_Membership
                              join tab2 in db.aspnet_Users on tab1.UserId equals tab2.UserId
                              select new
                              {
                                  tab1.UserId,
                                  tab2.UserName,
                                  tab1.Email,
                                  tab1.IsApproved
                              }

            );


            bool includeInActive = (bool)Session["includeInActiveAccount"];
            string charFilter = (string)Session["CharFilterAccount"];

            var result = sampleData.Where(ent => ((includeInActive || ent.IsApproved)));
            if ("0".Equals(charFilter))
            {
                result = sampleData.Where(ent => ((includeInActive || ent.IsApproved) &&
                    (ent.UserName.StartsWith("0") || ent.UserName.StartsWith("1") ||
                    ent.UserName.StartsWith("2") || ent.UserName.StartsWith("3") ||
                    ent.UserName.StartsWith("4") || ent.UserName.StartsWith("5") ||
                    ent.UserName.StartsWith("6") || ent.UserName.StartsWith("7") ||
                    ent.UserName.StartsWith("8") || ent.UserName.StartsWith("9")
                    )));
            }

            else
            {
                result = sampleData.Where(ent => ((includeInActive || (bool)ent.IsApproved) && ent.UserName.StartsWith(charFilter)));

            }

            // Sorting
            if (!string.IsNullOrEmpty(parameters.SimpleSort))
            {
                result = result.OrderBy(parameters.SimpleSort + (parameters.SimpleSortDirection == SortDirection.DESC ? " desc" : " asc"));
            }
            else
            {
                result = result.OrderBy(ent => ent.UserId);
            }

            // Paging
            int limit = parameters.Limit;
            if ((parameters.Start + parameters.Limit) > result.Count())
            {
                limit = result.Count() - parameters.Start;
            }

            var rangeData = (parameters.Start < 0 || limit < 0) ? result : result.Skip(parameters.Start).Take(limit);
            return this.Store(rangeData.Select(ent => new { ent.UserId, ent.UserName, ent.Email, ent.IsApproved }), result.Count());
        }

        // **************************************
        // URL: /Account/Profile
        // **************************************

        public ActionResult MyProfile()
        {
            var profile = new ProfileModel();
            var id = User.Identity.Name;
            var aspUser = db.aspnet_Users.SingleOrDefault(x => x.UserName == id);
            var user = db.Users.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var aspMember = db.aspnet_Membership.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var role = aspUser.aspnet_Roles.FirstOrDefault().RoleName;
            profile.UserName = aspUser.UserName;
            profile.Email = aspMember.Email;
            profile.Avatar = user.UserPhoto;
            profile.UserSignature = user.UserSignature;
            profile.CreateDate = aspMember.CreateDate;
            profile.Birthday = user.UserBirthDate;
            profile.Post = db.Comments.Count(x => x.UserId == aspUser.UserId);
            profile.Role = role;
            return View(profile);
        }
        [HttpGet]
        public ActionResult EditProfile()
        {
            var profile = new ProfileModel();
            var id = User.Identity.Name;
            var aspUser = db.aspnet_Users.SingleOrDefault(x => x.UserName == id);
            var user = db.Users.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var aspMember = db.aspnet_Membership.SingleOrDefault(x => x.UserId == aspUser.UserId);
            profile.UserName = aspUser.UserName;
            profile.Email = aspMember.Email;
            profile.Avatar = user.UserPhoto;
            profile.UserSignature = user.UserSignature;
            profile.Birthday = user.UserBirthDate;
            profile.Avatar = user.UserPhoto;
            return View(profile);
        }

        [HttpPost]
        [ValidateInput(false)]
        public ActionResult EditProfile(ProfileModel model)
        {
            var id = User.Identity.Name;
            var aspUser = db.aspnet_Users.SingleOrDefault(x => x.UserName == id);
            var user = db.Users.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var aspMember = db.aspnet_Membership.SingleOrDefault(x => x.UserId == aspUser.UserId);
            aspUser.UserName = model.UserName;
            aspMember.Email = model.Email;
            user.UserBirthDate = model.Birthday;
            user.UserSignature = model.UserSignature;
            var upImage = X.GetCmp<FileUploadField>("UpImage");
            if (upImage.HasFile)
            {
                var httpPostedFileBase = Request.Files[0];
                if (httpPostedFileBase != null)
                {
                    httpPostedFileBase.SaveAs(Server.MapPath("~/") + "//Content//Logo//" +
                                              httpPostedFileBase.FileName);
                    user.UserPhoto = "/Content/Logo/" + httpPostedFileBase.FileName;
                }
            }
            db.SaveChanges();
            return View();
        }

        public ActionResult ShowProfile(string userName)
        {
            var profile = new ProfileModel();
            var aspUser = db.aspnet_Users.SingleOrDefault(x => x.UserName == userName);
            var user = db.Users.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var aspMember = db.aspnet_Membership.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var role = aspUser.aspnet_Roles.FirstOrDefault().RoleName;
            profile.UserName = aspUser.UserName;
            profile.Email = aspMember.Email;
            profile.Avatar = user.UserPhoto;
            profile.UserSignature = user.UserSignature;
            profile.CreateDate = aspMember.CreateDate;
            profile.Birthday = user.UserBirthDate;
            profile.Post = db.Comments.Count(x => x.UserId == aspUser.UserId);
            profile.Role = role;
            return View(profile);
        }
    }



    ////
    //    //GET: /Account/ForgotPassword

    //    [AllowAnonymous]
    //    public ActionResult ForgotPassword()
    //    {
    //        return View();
    //    }

    //    //
    //    //POST: /Account/ForgotPassword

    //    [HttpPost]
    //    [AllowAnonymous]
    //    [ValidateAntiForgeryToken]
    //    public ActionResult ForgotPassword(string UserName)
    //    {
    //        //check user existance
    //        var user = Membership.GetUser(UserName);
    //        if (user == null)
    //        {
    //            TempData["Message"] = "User Not exist.";
    //        }
    //        else
    //        {
    //            //generate password token
    //            var token = WebSecurity.GeneratePasswordResetToken(UserName);
    //            //create url with above token
    //            var resetLink = "<a href='" + Url.Action("ResetPassword", "Account", new { un = UserName, rt = token }, "http") + "'>Reset Password</a>";
    //            //get user emailid
    //            UsersContext db = new UsersContext();
    //            var emailid = (from i in db.UserProfiles
    //                           where i.UserName == UserName
    //                           select i.EmailId).FirstOrDefault();
    //            //send mail
    //            string subject = "Password Reset Token";
    //            string body = "<b>Please find the Password Reset Token</b><br/>" + resetLink; //edit it
    //            try
    //            {
    //                SendEMail(emailid, subject, body);
    //                TempData["Message"] = "Mail Sent.";
    //            }
    //            catch (Exception ex)
    //            {
    //                TempData["Message"] = "Error occured while sending email." + ex.Message;
    //            }
    //            //only for testing
    //            //TempData["Message"] = resetLink;
    //        }

    //        return View();
    //    }

    //    [AllowAnonymous]
    //    public ActionResult ResetPassword(string un, string rt)
    //    {
    //        UsersContext db = new UsersContext();
    //        //TODO: Check the un and rt matching and then perform following
    //        //get userid of received username
    //        var userid = (from i in db.UserProfiles
    //                      where i.UserName == un
    //                      select i.UserId).FirstOrDefault();
    //        //check userid and token matches
    //        bool any = (from j in db.webpages_Memberships
    //                    where (j.UserId == userid)
    //                    && (j.PasswordVerificationToken == rt)
    //                    //&& (j.PasswordVerificationTokenExpirationDate < DateTime.Now)
    //                    select j).Any();

    //        if (any == true)
    //        {
    //            //generate random password
    //            string newpassword = GenerateRandomPassword(6);
    //            //reset password
    //            bool response = WebSecurity.ResetPassword(rt, newpassword);
    //            if (response == true)
    //            {
    //                //get user emailid to send password
    //                var emailid = (from i in db.UserProfiles
    //                               where i.UserName == un
    //                               select i.EmailId).FirstOrDefault();
    //                //send email
    //                string subject = "New Password";
    //                string body = "<b>Please find the New Password</b><br/>" + newpassword; //edit it
    //                try
    //                {
    //                    SendEMail(emailid, subject, body);
    //                    TempData["Message"] = "Mail Sent.";
    //                }
    //                catch (Exception ex)
    //                {
    //                    TempData["Message"] = "Error occured while sending email." + ex.Message;
    //                }

    //                //display message
    //                TempData["Message"] = "Success! Check email we sent. Your New Password Is " + newpassword;
    //            }
    //            else
    //            {
    //                TempData["Message"] = "Hey, avoid random request on this page.";
    //            }
    //        }
    //        else
    //        {
    //            TempData["Message"] = "Username and token not maching.";
    //        }

    //        return View();
    //    }

    //    //
    //    //function: Generate New Password

    //    private string GenerateRandomPassword(int length)
    //    {
    //        string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
    //        char[] chars = new char[length];
    //        Random rd = new Random();
    //        for (int i = 0; i < length; i++)
    //        {
    //            chars[i] = allowedChars[rd.Next(0, allowedChars.Length)];
    //        }
    //        return new string(chars);
    //    }

    //    //
    //    //function: Send Email Resset Password Link

    //    private void SendEMail(string emailid, string subject, string body)
    //    {
    //        SmtpClient client = new SmtpClient();
    //        client.DeliveryMethod = SmtpDeliveryMethod.Network;
    //        client.EnableSsl = true;
    //        client.Host = "smtp.gmail.com";
    //        client.Port = 587;

    //        System.Net.NetworkCredential credentials = new System.Net.NetworkCredential("djnhtan@gmail.com", "curve8800");
    //        client.UseDefaultCredentials = false;
    //        client.Credentials = credentials;

    //        MailMessage msg = new MailMessage();
    //        msg.From = new MailAddress("djnhtan@gmail.com");
    //        msg.To.Add(new MailAddress(emailid));

    //        msg.Subject = subject;
    //        msg.IsBodyHtml = true;
    //        msg.Body = body;

    //        client.Send(msg);
    //    }

}
